package com.zzyl.serve.service.impl;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zzyl.common.constant.RedisKeyConstant;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.framework.web.service.TokenService;
import com.zzyl.serve.domain.DeviceData;
import com.zzyl.serve.domain.Elder;
import com.zzyl.serve.dto.UserAddRequestDto;
import com.zzyl.serve.dto.UserLoginRequestDto;
import com.zzyl.serve.mapper.DeviceDataMapper;
import com.zzyl.serve.service.*;
import com.zzyl.serve.vo.DeviceDataGraphVo;
import com.zzyl.serve.vo.ElderPageVo;
import com.zzyl.serve.vo.HealthDataVo;
import com.zzyl.serve.vo.LoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.serve.mapper.FamilyMemberMapper;
import com.zzyl.serve.domain.FamilyMember;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import static com.zzyl.common.utils.UserThreadLocal.getUserId;

/**
 * 老人家属Service业务层处理
 * 
 * @author itheima
 * @date 2025-03-12
 */
@Service
public class FamilyMemberServiceImpl extends ServiceImpl<FamilyMemberMapper, FamilyMember> implements IFamilyMemberService
{
    @Autowired
    private FamilyMemberMapper familyMemberMapper;
    @Autowired
    private IDeviceDataService deviceDataService;
    @Qualifier("redisTemplate")
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private DeviceDataMapper deviceDataMapper;

    @Autowired
    private IElderService elderService;

    /**
     * 查询老人家属
     * 
     * @param id 老人家属主键
     * @return 老人家属
     */
    @Override
    public FamilyMember selectFamilyMemberById(Long id)
    {
        return getById(id);
    }

    /**
     * 查询老人家属列表
     * 
     * @param familyMember 老人家属
     * @return 老人家属
     */
    @Override
    public List<FamilyMember> selectFamilyMemberList(FamilyMember familyMember)
    {
        return familyMemberMapper.selectFamilyMemberList(familyMember);
    }

    /**
     * 新增老人家属
     * 
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int insertFamilyMember(FamilyMember familyMember)
    {
        return save(familyMember) ? 1 : 0;
    }

    /**
     * 修改老人家属
     * 
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int updateFamilyMember(FamilyMember familyMember)
    {
        return updateById(familyMember) ? 1 : 0;
    }

    /**
     * 批量删除老人家属
     * 
     * @param ids 需要删除的老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除老人家属信息
     * 
     * @param id 老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberById(Long id)
    {
        return removeById(id) ? 1 : 0;
    }


    @Autowired
    private WechatService webschatService;

    @Autowired
    private TokenService tokenService;

    /**
     *  小程序端 用户登录的逻辑处理
     * @param dto
     * @return
     */
    @Override
    public LoginVo login(UserLoginRequestDto dto) {


        //1.根据code调用微信api获取apenId
        String openid = webschatService.getOpenid(dto.getCode());

        //2.根据openId查询数据库获取用户信息family_member表
        FamilyMember familyMember = getOne(
                new LambdaQueryWrapper<FamilyMember>()
                        .eq(FamilyMember::getOpenId, openid)
        );

        //3.调用微信api获取用户绑定手机号
        String phone = webschatService.getPhone(dto.getPhoneCode());


        //4.判断用户信息是否存在，如果不存在，则新增family_member表
        //5.存在则 修改family_member表数据
        if(ObjectUtil.isNull(familyMember)){
            // 新用户


            familyMember = new FamilyMember();
            familyMember.setPhone(phone);
            familyMember.setOpenId(openid);

            // 设置初始随机名称
            familyMember.setName("花开富贵" + DateUtils.getTime());

            save(familyMember);

        }else {
            // 老用户
            familyMember.setPhone(phone);
            updateById(familyMember);
        }


        //6.将用户id存入token中，并返回数据给前端
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", familyMember.getId());
        claims.put("nickName", familyMember.getName());

        String token = tokenService.createToken(claims);
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setNickName(familyMember.getName());
        return loginVo;
    }

    /**
     * 按天统计查询指标数据
     *
     * @param functionId
     * @param startTime
     * @param endTime
     * @param iotId
     * @return
     */
    @Override
    public List<DeviceDataGraphVo> queryDeviceDataListByDay(String functionId, Long startTime, Long endTime, String iotId) {

        //将时间戳转换为LocalDateTime
        //开始时间
        LocalDateTime localDateTime = LocalDateTimeUtil.of(startTime);
        //结束时间
        LocalDateTime localDateTime2 = LocalDateTimeUtil.of(endTime);

        List<DeviceDataGraphVo> dayInstances = DeviceDataGraphVo.getDayInstances(localDateTime);

        for (int i = 0; i < dayInstances.size(); i++){
            String dateTime = dayInstances.get(i).getDateTime();
            String fullDateTimeStr = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " " + dateTime;
            LocalDateTime parseStartTime = LocalDateTime.parse(fullDateTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
            if (i == 23) {
                LambdaQueryWrapper<DeviceData> queryWrapper = new LambdaQueryWrapper<DeviceData>()
                        .eq(DeviceData::getFunctionId, functionId)
                        .eq(DeviceData::getIotId, iotId)
                        .ge(DeviceData::getAlarmTime, parseStartTime)
                        .lt(DeviceData::getAlarmTime, localDateTime2);
                DeviceData one = deviceDataService.getOne(queryWrapper, false);
                try {
                    dayInstances.get(i).setDataValue(Double.valueOf(one.getDataValue()));
                } catch (Exception e) {
                    continue;
                }
                return dayInstances;
            }
            String dateTime2 = dayInstances.get(i+1).getDateTime();
            String fullDateTimeStr2 = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " " + dateTime2;
            LocalDateTime parseEndTime = LocalDateTime.parse(fullDateTimeStr2, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));

            LambdaQueryWrapper<DeviceData> queryWrapper = new LambdaQueryWrapper<DeviceData>()
                    .eq(DeviceData::getFunctionId, functionId)
                    .eq(DeviceData::getIotId, iotId)
                    .ge(DeviceData::getAlarmTime, parseStartTime)
                    .lt(DeviceData::getAlarmTime, parseEndTime);
            DeviceData one = deviceDataService.getOne(queryWrapper, false);

            try {
                dayInstances.get(i).setDataValue(Double.valueOf(one.getDataValue()));
            } catch (Exception e) {
                continue;
            }
        }
        return dayInstances;
    }

    /**
     * 按周统计查询指标数据
     *
     * @return
     */
    @Override
    public List<DeviceDataGraphVo> queryDeviceDataListByWeek(String functionId,
                                                             Long startTime,
                                                             Long endTime,
                                                             String iotId) {
        //开始时间
        LocalDateTime localDateTime1 = LocalDateTimeUtil.of(startTime);
        //结束时间
//        LocalDateTime localDateTime2 = LocalDateTimeUtil.of(endTime);
        List<DeviceDataGraphVo> list = new ArrayList<>();

        for (int i = 0; i < 7; i++) {
            DeviceDataGraphVo deviceDataGraphVo = new DeviceDataGraphVo();
            deviceDataGraphVo.setDateTime(LocalDateTimeUtil.format(localDateTime1.plusDays(i), "MM:dd"));
            LocalDateTime localDateTime = localDateTime1.plusDays(i);
            //2025-05-14 00:00:00
            LocalDateTime startTimeZ = localDateTime.toLocalDate().atStartOfDay();
            //2025-05-15 00:00:00
            LocalDateTime endTimeZ = startTimeZ.plusHours(24);
//            LambdaQueryWrapper<DeviceData> queryWrapper = new LambdaQueryWrapper<DeviceData>()
//                    .eq(DeviceData::getFunctionId, functionId)
//                    .eq(DeviceData::getIotId, iotId)
//                    .ge(DeviceData::getAlarmTime, startTimeZ)
//                    .lt(DeviceData::getAlarmTime, endTimeZ)
//                    ;

            QueryWrapper<DeviceData> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("AVG(CAST(data_value AS DOUBLE))")
                    .lambda()
                    .eq(DeviceData::getFunctionId, functionId)
                    .eq(DeviceData::getIotId, iotId)
                    .ge(DeviceData::getAlarmTime, startTimeZ)
                    .lt(DeviceData::getAlarmTime, endTimeZ);
            List<Object> avgResult = deviceDataMapper.selectObjs(queryWrapper);
//            DeviceData one = deviceDataService.getOne(queryWrapper);
            if (ObjectUtil.isNull(avgResult)){
                list.add(deviceDataGraphVo);
                continue;
            }
            Object rawValue = avgResult.get(0);
            if (rawValue == null) {
                list.add(deviceDataGraphVo);
                continue;
            }
            Double dataValue = (Double) rawValue;
            DecimalFormat df = new DecimalFormat("#.0");
            String result = df.format(dataValue);

            Double finalValue = Double.parseDouble(result);
            deviceDataGraphVo.setDataValue(finalValue);
            list.add(deviceDataGraphVo);
        }
        return list;

    }

    /**
     * 查询健康数据
     *
     * @param iotId
     * @return
     */
    @Override
    public List<HealthDataVo> queryServiceProperties(String iotId) {
        List<HealthDataVo> voList = new ArrayList<>();
        //获取当前时间
        LocalDateTime now = LocalDateTime.now();

        //根据设备id在Redis中查询最新的值
        String jsonStr = (String) redisTemplate.opsForHash().get(RedisKeyConstant.IOT_DEVICE_LAST_DATA, iotId);
        if(StringUtils.isEmpty(jsonStr)){
            //返回一个空集合
            return List.of();
        }
        // 反序列化为对象
        List<DeviceData> deviceDataList = JSONUtil.toList(jsonStr, DeviceData.class);
        if (CollUtil.isEmpty(deviceDataList)) {
            throw new RuntimeException("数据不存在");
        }
        deviceDataList.forEach(item -> {
            HealthDataVo bean = BeanUtil.toBean(item, HealthDataVo.class);
            bean.setEventTime(LocalDateTime.parse(now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"))));
            String dataValueStr = item.getDataValue();
            int value = new BigDecimal(dataValueStr).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
            bean.setValue(value);
            voList.add(bean);
        });


        return voList;
    }


    // h
    /**
     * 绑定老人
     *
     * @param dto 老人
     * @return 结果
     */
    @Override
    public void BindingFamilyMember(UserAddRequestDto dto) {
        Long userId =getUserId();
        Elder elder = elderService.getOne(
                new LambdaQueryWrapper<Elder>()
                        .eq(Elder::getIdCardNo, dto.getIdCard())
                        .eq(Elder::getName,dto.getName())
        );
        if (elder == null) {
            throw new RuntimeException("老人信息错误");
        }
        List<Map<String, Object>> familymember = familyMemberMapper.find(userId, elder.getId());
        if (familymember.size() > 0){
            throw new RuntimeException("您已绑定该老人");
        }
        LocalDateTime createTime  =  LocalDateTime.now();
        familyMemberMapper.BindingFamilyMember(userId, elder.getId(), createTime,dto.getRemark());
    }

    /**
     * 查询家人列表
     *
     * @return 结果
     */
    @Override
    public List<Map<String, Object>> myFamilyMember() {
        return familyMemberMapper.myFamilyMember();
    }

    /**
     * 查询家人列表（分页查询）
     *
     * @return 结果
     */
    @Override
    public List<ElderPageVo> PageFamilyMember() {
        Long userId =getUserId();
        return familyMemberMapper.PageFamilyMember(userId);
    }

    /**
     * 解绑家人
     *
     * @param id
     */
    @Override
    public void deleteByIdFamilyMember(Integer id) {
        familyMemberMapper.deleteByIdFamilyMember(id);
    }
}
